package com.cw.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cw.common.constant.Constants;
import com.cw.common.constant.Response;
import com.cw.common.method.SendCardMsg;
import com.cw.dto.ApplicationBedDTO;
import com.cw.entity.*;
import com.cw.mapper2.*;
import com.cw.request.BedAppicationDownLoad;
import com.cw.service.IApplicationBedService;
import com.cw.util.*;
import com.github.pagehelper.PageInfo;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ly
 * @since 2021-12-13
 */
@Service
public class ApplicationBedServiceImpl extends ServiceImpl<ApplicationBedMapper, ApplicationBed> implements IApplicationBedService {

    Lock lock = new ReentrantLock();

    @Autowired
    private WeChatLogMapper weChatLogMapper;

    @Autowired
    private REmployeeMapper rEmployeeMapper;

    @Autowired
    private PatientBedMiddlePrebundledMapper patientBedMiddlePrebundledMapper;

    @Autowired
    private MqLogMapper mqLogMapper;


    private MQMsg mqMsg = new MQMsg();

    @Override
    public Boolean getISNotice(ApplicationBed entity) {
        List<ApplicationBed> inquire = baseMapper.getInquire(entity);
        List<ApplicationBed> request = inquire.stream().filter(t -> t.getIsNotice().equals("0")).collect(Collectors.toList());
        List<BigDecimal> listPreId = request.stream().map(t -> t.getPreid()).collect(Collectors.toList());
        lock.lock();
        try {
            baseMapper.UpdateBatchApplicationStatus(listPreId, "1", null);
        } catch (Exception ex) {
            int a = 1;
        } finally {
            lock.unlock();
        }
        return CollectionUtil.isNotEmpty(request);
    }

    @Override
    public Response addPopup(ApplicationBed entity) {
        try {
            Date currDate = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = DateUtil.date();
            String formatDate = DateUtil.formatDate(date);
            entity.setCreateTime(sdf.format(currDate));
            entity.setUpdateTime(sdf.format(currDate));
            entity.setNucleicacid(formatDate);
            baseMapper.addPopup(entity);
        } catch (Exception ex) {
            return Response.error(String.join(":", "添加失败:", ex.getMessage()));
        }
        return Response.success("申请成功");
    }

    @Override
    public Response UpdateApplication(ApplicationBed entity) {
        try {
            Date currDate = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            entity.setCreateTime(sdf.format(currDate));
            entity.setUpdateTime(sdf.format(currDate));
            String userName = HttpUtil.getRequestHeaderInfo(Constants.USER_NAME);
            userName = userName == null || userName.isEmpty() ? "System" : userName;
            entity.setCreateBy(userName);
            entity.setUpdateBy(userName);
            baseMapper.UpdateApplication(entity);
        } catch (Exception ex) {
            return Response.error(String.join(":", "修改失败:", ex.getMessage()));
        }
        return Response.success("修改成功");
    }

    @Override
    public Response UpdateBatchApplicationStatus(List<BigDecimal> lstPreid, String isNotice, String isHandle) {
        try {
            baseMapper.UpdateBatchApplicationStatus(lstPreid, null, isHandle);
        } catch (Exception ex) {
            return Response.error(String.join(":", "修改失败:", ex.getMessage()));
        }
        return Response.success("修改成功");
    }

    @Override
    public List<ApplicationBed> getInquire(ApplicationBed entity) {
        return baseMapper.getInquire(entity);
    }

    /**
     * 床位申请表查询
     *
     * @param entity
     * @return
     */
    @Override
    public PageInfo<BedUggIeCWInfo> getBedReservationQuery(ApplicationBed entity) {
        List<BedUggIeCWInfo> bedapplicationList = baseMapper.getBedReservationQuery(entity);
        //预绑定患者信息查询
        List<PatientBedMiddlePrebundled> patientBedMiddlePrebundleds = patientBedMiddlePrebundledMapper.patientList();
        if (!patientBedMiddlePrebundleds.isEmpty()){
            List<String> preidListString = new ArrayList<>();
            List<BigDecimal> preidList = patientBedMiddlePrebundleds.stream()
                    .map(PatientBedMiddlePrebundled::getPreid)
                    .collect(Collectors.toList());
            for (BigDecimal decimal : preidList) {
                String toString = decimal.toString();
                preidListString.add(toString);
            }
            //预绑定的患者过滤掉
            bedapplicationList = bedapplicationList.stream()
                    .filter(t -> !preidListString.contains(t.getPreid()))
                    .collect(Collectors.toList());
        }
        //拿到非集管床位校验跟Middle表里关联到的患者
        for (BedUggIeCWInfo bedlist:bedapplicationList) {
            if (bedlist.getExtendField1()!=null&&!bedlist.getExtendField1().isEmpty()){
                bedlist.setInspectionStatus("1");
            }
        }
        int pageIndex = entity.getPageIndex();
        int pageSize = entity.getPageSize();
        return PageHelperTool.excutePageInfo(bedapplicationList, pageIndex, pageSize);
    }

    @Override
    public Response Deleteinformation(List<BigDecimal> ids) {
        try {
            baseMapper.Deleteinformation(ids);
        } catch (Exception ex) {
            return Response.error("删除失败");
        }
        return Response.success("删除成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response deleteByPreid(List<String> Listpreid) {
        try {
            baseMapper.deleteByPreid(Listpreid);
        } catch (Exception ex) {
            return Response.error(String.join(":", "修改失败:", ex.getMessage()));
        }
        return Response.success("修改成功");
    }

    /**
     * 床位申请报表下载
     *
     * @param requestInfo
     * @author xnd
     * @since 2022-3-29
     */
    @Override
    public void geBedApplicationDownLoadExcel(BedAppicationDownLoad requestInfo) throws IOException {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        List<ApplicationBed>applicationBedList =getBedApplication(requestInfo);
        applicationBedList.forEach(item->{
            if (item.getIsCrossNurse().equals("0")){
                item.setIsCrossNurse("否");
            }else if (item.getIsCrossNurse().equals("1")){
                item.setIsCrossNurse("是");
            }
            if (item.getSex().equals("1")){
                item.setSex("男");
            }else  if (item.getSex().equals("2")){
                item.setSex("女");
            }
            if (item.getCreateBy().isEmpty()&&item.getCreateBy().equals("")){
                item.setCreateBy("无");
            }
            if (item.getRootState().equals("0")){
                item.setRootState("已删除");
            }else if (item.getRootState().equals("1")){
                item.setRootState("当前在院患者");
            }
        });
       //Excel报表字段变色
        Map<String,Map<String, IndexedColors>> map =new HashMap<>();
        Map<String,IndexedColors> childernMap =new HashMap<>();
        childernMap.put("已删除",IndexedColors.RED);
        childernMap.put("当前在院患者", IndexedColors.GREEN);
        map.put("rootState",childernMap);

        String name = String.valueOf(System.currentTimeMillis());
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode(name, "UTF-8");
        // 根据用户传入字段  set是删除字段
        Set<String> excludeColumnFiledNames = new HashSet<String>();
        excludeColumnFiledNames.add("deptCode");
        excludeColumnFiledNames.add("nurseCellCode");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx;");
//        EasyExcel.write(response.getOutputStream(), ApplicationBed.class).registerConverter(new LocalDateTimeConverter()).excludeColumnFiledNames(excludeColumnFiledNames).sheet("sheet").doWrite(applicationBedList);
        EasyExcel.write(response.getOutputStream(),ApplicationBed.class).registerWriteHandler(CellColorUtil.cellFontColorBySameValue(applicationBedList,map,"sheet")).sheet("sheet").doWrite(applicationBedList);

    }

    @Override
    @Transactional
    public Response sendMessageToDoctor(ApplicationBedDTO dto) {
        // 企业微信编号
        LambdaQueryWrapper<REmployee> lambdaQueryEmployeeWrapper = new LambdaQueryWrapper<>();
        lambdaQueryEmployeeWrapper.eq(REmployee::getEmplCode, dto.getJobNumber());
        REmployee retREmployee = rEmployeeMapper.selectOne(lambdaQueryEmployeeWrapper);
        MsgInfo msgInfo = getMsgInfo(retREmployee,dto);
        new Thread(() -> {
            //发送企业微信
            setMsg(msgInfo);
            if (msgInfo.getWechatAccountCode() != null && !msgInfo.getWechatAccountCode().isEmpty()) {
                //企业微信返回josn消息体
                try {
                //调用post发送企业微信消息
                    WeChatLog weChatLog = SendCardMsg.send4(msgInfo);
                    weChatLogMapper.insert(weChatLog);
                } catch (IOException e) {
                    int a = 0;
                }
            }
        }).start();
        return Response.success("发送成功");
    }

    private void setMsg(MsgInfo msgInfo) {
        // 设定用户
        mqMsg.setUserName("S01");
        // 设定密码
        mqMsg.setPassword("123456");
        // 设定通道池
        mqMsg.setQueueManagerName("QMGR.P01");
        // 设定消息频道
        mqMsg.setChannel("PS35035");

        mqMsg.setPatName(msgInfo.getName());                // 设定姓名
        mqMsg.setPatIndexNo(msgInfo.getPatientNo()); // 索引号
        mqMsg.setMsgTitle(msgInfo.getTitle());
        //发给个人
        mqMsg.setMessageType("2");
        // 设定消息内容
        mqMsg.setMsgContent("患者:" + msgInfo.getName() + "(" + msgInfo.getDeptName() + ") " + msgInfo.getResult() + msgInfo.getYardName() + "院区-" + msgInfo.getNurseCellName() + msgInfo.getBedNum() + "床位");
        mqMsg.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        mqMsg.setSenderCode(msgInfo.getEmplCode());        // 设定发送者工号
        mqMsg.setSenderName(msgInfo.getEmplName());        // 设定发送者姓名
        mqMsg.setBedNum(msgInfo.getBedNum());        // 设定床位号
        mqMsg.setDeptCode(msgInfo.getDeptCode());    // 设定科室编号
        mqMsg.setDeptName(msgInfo.getDeptName());    // 设定科室名称
        mqMsg.setWardCode(msgInfo.getNurseCellCode());    // 病区代码
        // 设定病区名称
        mqMsg.setWardName(msgInfo.getNurseCellName());
        // 设定院区编号
        mqMsg.setHospDistrictCode(msgInfo.getYard());
        // 设定院区
        mqMsg.setHostDistrictName(msgInfo.getYardName());
        mqMsg.setReciveCode(msgInfo.getEmplCode());
        mqMsg.setReciveName(msgInfo.getEmplName());
        String xmlString = mqMsg.createXMLString(mqMsg);

        MqLog mqLog = new MqLog();
        String uuid = UUIDUtil.uuid();
        mqLog.setId(uuid);
        mqLog.setRequestMsg(xmlString);
        mqLog.setRequestDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        mqLog.setSenderCode(msgInfo.getEmplCode());
        mqLog.setSenderName(msgInfo.getEmplName());
        String msgId = mqMsg.putMsg(xmlString);
        mqLog.setMsgId(msgId);
        if (msgId != "") {
            mqLog.setResponseType("success");
        } else {
            mqLog.setResponseType("fail");
        }
        mqLogMapper.insert(mqLog);
    }

    private MsgInfo getMsgInfo(REmployee retREmployee, ApplicationBedDTO dto) {
        MsgInfo info = new MsgInfo();
        info.setEmplCode(dto.getJobNumber());
        info.setEmplName(retREmployee.getEmplName());
        info.setName(dto.getName());
        info.setPatientName(dto.getName());
        info.setNurseCellName(dto.getNurseCellName());
        info.setDiagName(dto.getDiagName());
        info.setRemark(dto.getRemark());
        info.setTitle("消息通知");
        info.setWechatAccountCode(retREmployee.getXgzh());
        return info;
    }

    private List<ApplicationBed> getBedApplication(BedAppicationDownLoad requestInfo) {
        List<ApplicationBed> AllBedApplication = new ArrayList<>();
        List<ApplicationBed> applicationBedList =baseMapper.getBedapplication(requestInfo);
        //跨区患者
        List<ApplicationBed> CrossRegionalPatients = applicationBedList.stream().filter(t -> t.getIsCrossNurse().equals("1")).collect(Collectors.toList());
        //不跨区
        List<ApplicationBed> NoCrossRegionalPatients = applicationBedList.stream().filter(t -> t.getIsCrossNurse().equals("0")).collect(Collectors.toList());
        //""是全部的
        if ("2".equals(requestInfo.getIsCrossNurse())||requestInfo.getIsCrossNurse().isEmpty()){
            AllBedApplication.addAll(CrossRegionalPatients);
            AllBedApplication.addAll(NoCrossRegionalPatients);
        }
        //0不是跨区的
        else if("0".equals(requestInfo.getIsCrossNurse()))
        {
            AllBedApplication.addAll(NoCrossRegionalPatients);
        }
        //1是跨区的
        else if ("1".equals(requestInfo.getIsCrossNurse()))
        {
            AllBedApplication.addAll(CrossRegionalPatients);
        }
        if(CollectionUtils.isEmpty(AllBedApplication))
        {
            return new ArrayList<>();
        }
        return AllBedApplication;
    }
}
